import sys
from collections import namedtuple

import numpy as np
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QGraphicsView, QFrame, QHBoxLayout
from PyQt5.QtChart import QChart, QChartView, QLineSeries, QValueAxis
from PyQt5.QtGui import QPen, QColor, QPainter
from PyQt5.QtCore import Qt, QPointF
from PyQt5.QtWidgets import QDockWidget

# 创建可交互式水平可视化窗口
# 使用使用QGraphic创建
# 模拟数据
# np.random.seed(0)
num_points = 50  # 增加数据点以便图表更明显
well_id = 'A1'
depths = np.linspace(1000, 2000, num_points)
rock_desc = ['砂岩', '泥岩', '灰岩']
analyst = '张三'
date = '2024-06-01'
types = ['a', 'b', 'c']
# 模拟
element_to_simulate = {
    "Mg": (0, 15, QColor(255,0,0)),
    "Al": (5, 20, QColor(0,150,255)),
    "Si": (10, 25, QColor(0,200,0)),
}

data = []

for i in range(num_points):
    row = {'井号':well_id,'深度':depths[i]}
    for element,(min_val,max_val,_) in element_to_simulate.items():
        row[element]=np.random.uniform(min_val,max_val)  # 随机生成元素含量
    data.append(row)


class CurveLabel(QLabel):
    def __init__(self, name,color,parent=None):
        super().__init__(name, parent)
        self.setFixedHeight(24)#解释: 设置标签高度
        # 设置标签的背景颜色和文本颜色
        self.setStyleSheet(f"background-color: {color.name()}; color: white; border-radius: 4px; padding:2px 8px;")
        self.setCursor(Qt.CursorShape.OpenHandCursor)#设置鼠标光标为手型
        self.name=name
        self.color=color
        self.drag_start_pos=None  # 用于记录拖动开始位置
        self.setMouseTracking(True)  # 启用鼠标跟踪

    def enterEvent(self, event):#鼠标进入事件
        pass

    def leaveEvent(self, event):#鼠标离开事件
        pass

    def mousePressEvent(self,event):#解释: 鼠标按下事件
        pass
    def mouseMoveEvent(self, event):#解释: 鼠标移动事件
        pass

class TrackWidget(QFrame):
    def __init__(self,series_info_list,xdata,parent=None,bg_index=0):
        super().__init__(parent)#调用父类 QFrame 的构造函数，保证控件能正常嵌入到 Qt 的控件体系中。
        self.setFrameShape(QFrame.StyledPanel)  # 设置边框样式
        self.setAcceptDrops(True)  # 允许拖放操作 允许该控件接收拖拽事件（比如曲线标签或轨道的拖拽）。
        self.series_info_list= series_info_list  # 存储系列信息列表
        self.xdata = xdata  # 存储x轴数据
        self.bg_index = bg_index  # 背景索引，用于设置背景颜色
        self.init_ui()  # 初始化UI组件

    def init_ui(self):
        layout=QHBoxLayout(self)
        #交替背景色
        if self.bg_index % 2==0:
            self.setStyleSheet("background-color:#F7F7F7;")  # 浅灰色背景
        else:
            self.setStyleSheet("background-color:#E9F5FF;")
        #y轴标签
        self.label_area=QWidget(self)
        self.label_layout=QVBoxLayout()
        # 这行代码设置了布局中各个控件（即曲线标签）之间的垂直间距为 2 像素，使标签之间不会紧贴在一起，界面更美观。
        self.label_layout.setSpacing(2)
        self.label_area.setLayout(self.label_layout)
        self.curve_labels=[]# 存储曲线标签的列表
        # 遍历 series_info_list，创建曲线标签
        for name, color,ydata in self.series_info_list:
            label=CurveLabel(name, color,parent=self.label_area)
            self.label_layout.addWidget(label)  # 将标签添加到布局中
            self.curve_labels.append(label)  # 将标签添加到曲线标签列表中
        layout.addWidget(self.label_area)  # 将标签区域添加到主布局中

        #折线图
        self.chart=QChart()
        self.chart.setBackgroundVisible(False)
        self.chart.legend().hide()#隐藏图例
        self.axisX=QValueAxis()
        self.axisX.setTitleText("")
        self.axisX.setLabelFormat("%.1f")
        self.axisX.setTickCount(6)#刻度数量
        self.axisX.setRange(min(self.xdata), max(self.xdata))
        self.axisY = QValueAxis()
        self.axisY.setTitleText("")
        self.axisY.setLabelFormat("%.1f")
        self.axisY.setTickCount(6)
        all_y=[]#解释:获取所有y轴数据
        for _,_,ydata in self.series_info_list:
            all_y.extend(ydata)#将所有y轴数据添加到all_y列表
        self.axisY.setRange(min(all_y), max(all_y))  # 设置y轴范围
        self.chart.addAxis(self.axisX,Qt.AlignmentFlag.AlignBottom)  # 将x轴添加到图表 ：指定 x 轴显示在图表的底部。
        self.chart.addAxis(self.axisY,Qt.AlignmentFlag.AlignLeft)  # 将y轴添加到图表
        self.series_objs=[]# 存储折线系列的列表
        for name, color, ydata in self.series_info_list:
            series = QLineSeries()
            series.setName(name)
            pen = QPen(color)
            pen.setWidth(2)
            series.setPen(pen)
            for x, y in zip(self.xdata, ydata):
                series.append(QPointF(x, y))
            self.chart.addSeries(series)
            series.attachAxis(self.axisX)# 将x轴关联到系列
            series.attachAxis(self.axisY)# 将y轴关联到系列
            self.series_objs.append(series)
        self.chart_view = QChartView(self.chart)
        self.chart_view.setRenderHint(QPainter.Antialiasing)  # 抗锯齿渲染
        self.chart_view.setFixedHeight(320)
        layout.addWidget(self.chart_view)
        self.setLayout(layout)
        self.setMouseTracking(True)

        #设置网格
        self.axisX.setGridLineVisible(True)  # 显示网格线
        self.axisY.setGridLineVisible(True)  # 显示网格线
        # 可选：设置网格线颜色和样式
        grid_pen = QPen(QColor(200, 200, 200), 1, Qt.DashLine)
        self.axisX.setGridLinePen(grid_pen)
        self.axisY.setGridLinePen(grid_pen)

    # 添加曲线
    def add_curve(self, name, color, ydata):
        self.series_info_list.append((name, color, ydata))  # 添加曲线信息到列表
        label = CurveLabel(name, color, parent=self.label_area)  # 创建曲线标签
        self.label_layout.addWidget(label)  # 将标签添加到标签布局中
        self.curve_labels.append(label)  # 将标签对象加入曲线标签列表
        series = QLineSeries()  # 创建折线对象
        series.setName(name)
        pen = QPen(color)
        pen.setWidth(2)
        series.setPen(pen)
        for x, y in zip(self.xdata, ydata):
            series.append(QPointF(x, y))  # 添加每个点到折线
        self.chart.addSeries(series)  # 添加折线到图表
        series.attachAxis(self.axisX)  # 绑定x轴
        series.attachAxis(self.axisY)  # 绑定y轴
        self.series_objs.append(series)  # 保存折线对象
        all_y = []
        for _, _, ydata in self.series_info_list:
            all_y.extend(ydata)
        self.axisY.setRange(min(all_y), max(all_y))  # 更新y轴范围

    # 删除曲线
    def remove_curve(self, name):
        idx = None
        for i, (n, _, _) in enumerate(self.series_info_list):
            if n == name:
                idx = i
                break
        if idx is not None:
            self.series_info_list.pop(idx)  # 移除曲线信息
            label = self.curve_labels.pop(idx)  # 移除标签对象
            label.setParent(None)  # 从界面移除标签
            series = self.series_objs.pop(idx)  # 移除折线对象
            self.chart.removeSeries(series)  # 从图表移除折线
            all_y = []
            for _, _, ydata in self.series_info_list:
                all_y.extend(ydata)
            if all_y:
                self.axisY.setRange(min(all_y), max(all_y))  # 更新y轴范围

    # 获取曲线信息
    def get_curve_info(self, name):
        for n, color, ydata in self.series_info_list:
            if n == name:
                return (n, color, ydata)
        return None

#多轨道拖拽示例主空件
class MultiTrackWidget(QWidget):
    def __init__(self, tracks_data, xdata):#解释:tracks_data:轨道数据,xdata:x轴数据
        super().__init__()
        self.xdata=xdata# x轴数据
        self.track_widgets=[]#所有轨道的 TrackWidget 列表
        #拖拽插入指示条
        self.drag_indicator=QFrame()
        self.drag_indicator.setFixedHeight(10)
        self.drag_indicator.setStyleSheet("background-color: yellow; border: 1px solid orange;")
        self.drag_indicator.hide()
        # 合并指示条
        self.merge_indicator = QFrame()
        self.merge_indicator.setStyleSheet("background-color: rgba(255,255,0,120); border: 2px solid orange;")
        self.merge_indicator.hide()#隐藏该指示条
        self.merge_target = None  # 合并目标轨道
        self.insert_index = None  # 插入目标索引
        self.init_ui(tracks_data)  # 初始化界面

    def init_ui(self, tracks_data):
        self.vlayout = QVBoxLayout()
        self.vlayout.setSpacing(5)
        # 创建每个轨道控件
        for idx, (name, ydata, color) in enumerate(tracks_data):
            track = TrackWidget([(name, color, ydata)], self.xdata, bg_index=idx)
            self.vlayout.addWidget(track)
            self.track_widgets.append(track)
        # x轴标签
        self.xaxis_label = QLabel(" " * 10 + "深度/时间轴" + " " * 10)
        self.xaxis_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.xaxis_label.setStyleSheet("font-weight:bold;font-size:16px;")
        self.vlayout.addWidget(self.xaxis_label)
        self.setLayout(self.vlayout)
        self.setAcceptDrops(True)  # 允许拖拽

    # 拖拽生成新轨道
    def add_new_track(self, info, from_track):
        idx = self.vlayout.indexOf(from_track)
        if idx == -1:
            idx = len(self.track_widgets)
        new_track = TrackWidget([info], self.xdata, bg_index=(idx + 1) % 2)
        self.vlayout.insertWidget(idx + 1, new_track)
        self.track_widgets.insert(idx + 1, new_track)

#截止6.2 23:41
    #拖拽进入事件
    def dragEnterEvent(self, a0):
        if a0 is None:
            a0.accept()  # 如果没有拖拽数据，接受事件

    #拖拽移动时间,判断位置并显示指示条

    def dragMoveEvent(self, a0):
        if a0 is None:
            return
        pos = a0.pos()
        self.merge_target = None
        self.insert_index = None
        found = False
        for i, track in enumerate(self.track_widgets):
            top = track.y()#解释:获取轨道顶部位置
            bottom = top + track.height()#解释:获取轨道底部位置
            merge_zone_top = top + track.height() * 0.2#解释:获取合并区域顶部位置
            merge_zone_bottom = bottom - track.height() * 0.2#解释:获取合并区域底部位置
            if merge_zone_top < pos.y() < merge_zone_bottom:
                self._show_merge_indicator(track)  # 显示合并指示条
                self.merge_target = track
                self.insert_index = None
                track.setStyleSheet(track.styleSheet() + "border:2px solid #FFA500;")
                found = True
                break
            elif top <= pos.y() < merge_zone_top:
                self._show_insert_indicator(i)  # 显示插入指示条
                self.merge_target = None
                self.insert_index = i
                found = True
                break
            elif merge_zone_bottom <= pos.y() < bottom:
                self._show_insert_indicator(i+1)
                self.merge_target = None
                self.insert_index = i+1
                found = True
                break
            else:
                track.setStyleSheet(track.styleSheet().replace("border:2px solid #FFA500;", ""))
        if not found:
            self._show_insert_indicator(len(self.track_widgets))
            self.merge_target = None
            self.insert_index = len(self.track_widgets)
        a0.accept()

    # 拖拽离开事件，隐藏所有指示条
    def dragLeaveEvent(self, a0):
        self.drag_indicator.hide()
        self.merge_indicator.hide()
        for track in self.track_widgets:
            track.setStyleSheet(track.styleSheet().replace("border:2px solid #FFA500;", ""))
        if a0 is not None and hasattr(a0, 'accept'):
            a0.accept()

    #拖拽释放事件,执行合并/插入操作
    def dropEvent(self, a0):
        self.drag_indicator.hide()
        self.merge_indicator.hide()
        for track in self.track_widgets:
            track.setStyleSheet(track.styleSheet().replace("border:2px solid #FFA500;", ""))
        if a0 is None:
            return
        src=a0.source()  # 获取拖拽源
        if isinstance(src, CurveLabel):  # 拖拽的是曲线标签
            for track in self.track_widgets:
                if src in track.curve_labels:
                    name = src.name
                    info = track.get_curve_info(name)
                    if info is not None:
                        track.remove_curve(name)  # 从原轨道移除
                        if not track.series_info_list:
                            self.vlayout.removeWidget(track)
                            self.track_widgets.remove(track)
                        if self.merge_target is not None:
                            self.merge_target.add_curve(*info)  # 合并到目标轨道
                        elif self.insert_index is not None:
                            new_track = TrackWidget([info], self.xdata, bg_index=self.insert_index % 2)
                            self.vlayout.insertWidget(self.insert_index, new_track)
                            self.track_widgets.insert(self.insert_index, new_track)
                    break
        elif isinstance(src, TrackWidget):  # 拖拽的是整个轨道
            if self.merge_target is not None and src != self.merge_target:
                for name, color, ydata in src.series_info_list[:]:
                    self.merge_target.add_curve(name, color, ydata)
                    src.remove_curve(name)
                self.vlayout.removeWidget(src)
                self.track_widgets.remove(src)
            elif self.insert_index is not None:
                if src in self.track_widgets:
                    idx_from = self.vlayout.indexOf(src)
                    idx_to = self.insert_index
                    if idx_from < idx_to:
                        idx_to -= 1
                    self.vlayout.removeWidget(src)
                    self.vlayout.insertWidget(idx_to, src)
                    self.track_widgets.remove(src)
                    self.track_widgets.insert(idx_to, src)
        a0.accept()

    # 显示插入指示条
    def _show_insert_indicator(self, index):
        self.merge_indicator.hide()
        self.drag_indicator.hide()
        if self.vlayout.indexOf(self.drag_indicator) != -1:
            self.vlayout.removeWidget(self.drag_indicator)
        if index is not None:
            self.vlayout.insertWidget(index, self.drag_indicator)
            self.drag_indicator.show()

    # 显示合并指示条
    def _show_merge_indicator(self, track):
        self.drag_indicator.hide()
        self.merge_indicator.hide()
        if self.merge_indicator.parent() is not None:
            self.merge_indicator.setParent(None)
        self.merge_indicator.setFixedHeight(track.height())
        self.vlayout.insertWidget(self.vlayout.indexOf(track), self.merge_indicator)
        self.merge_indicator.show()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("多轨道折线图重叠/独立拖拽示例（优化版）")
        self.setGeometry(100, 100, 1000, 600)
        tracks_data = []
        for name, (vmin, vmax, color) in element_to_simulate.items():
            ydata = [row[name] for row in data]
            tracks_data.append((name, ydata, color))
        self.widget = MultiTrackWidget(tracks_data, [row['深度'] for row in data])
        self.setCentralWidget(self.widget)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())  # 启动主事件循环


